﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using DiarySocial.BLL;
using DiarySocial.Models;
using DiarySocial.ViewModels;
using DiarySocial.ViewModels.Profile;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using WebMatrix.WebData;
using DiarySocial.Filters;
using System.Data;
using System.Data.Entity;

namespace DiarySocial.Controllers
{
    [Authorize]
    [InitializeSimpleMembership]
    public class DiaryController : Controller
    {
        private DiaryBLL diaryDB = new DiaryBLL();
        private DiaryEnties db = new DiaryEnties();

        //
        // GET: /Diary/Post
        [Authorize]
        public ActionResult Post()
        {
            var model = new DiaryPost();
            return View(model);
        }

        //
        // POST: /Diary/Post
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize]
        public ActionResult Post([Bind(Include = "Body")]DiaryPost diaryPost)
        {
            var model = new DiaryPost()
            {
                Body = diaryPost.Body
            };
            if (Request.IsAjaxRequest())
            {
                return PartialView("_PostDiaryAjax", model);
            }
            return Redirect(Url.Content("~"));
        }

        // AJAX POST: /Diary/QuickPost

        [HttpPost, Authorize]
        //[ValidateAntiForgeryToken]
        public JsonResult QuickPost(string body, int privacy, int lastId = 0)
        {
            var success = false;
            var diaryId = 0;
            var maxPrivacy = (int)(Enum.GetValues(typeof(PrivacyType)).Cast<PrivacyType>().Max());
            ICollection<TimeLineItemVM> stories = null;
            if (ModelState.IsValid && !string.IsNullOrEmpty(body.Trim()) && privacy >= 0 && privacy <= maxPrivacy)
            {
                var userId = WebSecurity.GetUserId(User.Identity.Name);
                if (diaryDB.QuickPost(userId, body, privacy))
                {
                    success = true;
                    diaryId = diaryDB.getLastDiaryId(userId);
                }
            }
            var result = new
            {
                success = success,
                id = diaryId,
            };
            return Json(result);
        }

        // GET /Diary/Comment
        public ActionResult Comment(int id)
        {
            var userId = WebSecurity.GetUserId(User.Identity.Name);
            var model = diaryDB.GetComments(userId, id);
            if (Request.IsAjaxRequest())
            {
                return PartialView("_GetCommentAjax", model);
            }
            return View(model);
        }

        [HttpPost]
        [ActionName("Comment")]
        [Authorize]
        public ActionResult SendComment(int id, string commentText)
        {
            var userId = WebSecurity.GetUserId(User.Identity.Name);
            try
            {
                diaryDB.SendComment(userId, id, commentText);
            }
            catch (DiaryBLLExeption e)
            {
                Console.WriteLine("Error" + e);
            }
            if (!Request.IsAjaxRequest()) return Redirect(@Url.Action("Comment", "Diary", new { id = id }));
            var model = diaryDB.GetComments(userId, id);
            return PartialView("_SendCommentAjax", model);
        }
        [HttpPost, Authorize]
        public JsonResult Like(int id, bool isLike)
        {
            var userId = WebSecurity.GetUserId(User.Identity.Name);
            return Json(!ModelState.IsValid ? diaryDB.JLikeError() : diaryDB.JLike(userId, id, isLike));
        }

        [HttpPost, Authorize]
        public JsonResult GetLikedUsers(int id)
        {
            return Json(diaryDB.JGetLikedUsers(0, id));
        }
        //
        // GET: /Diary/
        [Authorize]
        public ActionResult Index()
        {
            var userId = WebSecurity.GetUserId(User.Identity.Name);
            var stories = diaryDB.GetFriendStories(userId, 0, 10);
            var widget = new TimeLineWidgetVM()
            {
                Items = stories,
                Post = new TimeLineItemVM()
                {
                    Author = new AuthorVM(User.Identity.Name, (int)PrivacyType.Friend)
                }
            };
            return View(widget);
        }

        [Authorize]
        public ActionResult Profile(string id)
        {
            var username = id ?? User.Identity.Name;
            var userId = WebSecurity.GetUserId(username);
            if (userId == 0) throw new HttpException(404, "username not found");
            var owner = id == null || username.Equals(User.Identity.Name);
            var model = new ProfileVM()
            {
                IsLoadedAbout = true,
                About = diaryDB.getAboutContent(userId, username),
                IsLoadedFriend = true,
                Friends = diaryDB.getFriendContent(userId, WebSecurity.GetUserId(User.Identity.Name)),
            };
            model.About.Account = username;
            model.Owner = owner;
            if (String.IsNullOrWhiteSpace(model.About.DisplayName)) model.About.DisplayName = username;
            return View(model);
        }

        [Authorize, HttpPost]
        public JsonResult UpdateAbout([Bind(Include = "Email, DisplayName, Job, School, Address, Introduce")]About about)
        {
            var userId = WebSecurity.CurrentUserId;
            var success = diaryDB.updateAbout(userId, about);
            return Json(new
            {
                success = success
            });
        }

        [HttpPost, Authorize]
        public JsonResult RemoveAvatar()
        {
            var userId = WebSecurity.CurrentUserId;
            diaryDB.RemoveAvatar(userId);
            return Json(new
            {
                success = true,
                avatar = AppConst.DEFAULT_AVATAR_URL,
            });
        }

        [HttpPost, Authorize]
        public JsonResult ChangeAvatar(HttpPostedFileBase fileData)
        {
            var avatar = AppConst.DEFAULT_AVATAR_UPLOAD_PATH;
            if (fileData != null && fileData.ContentLength > 0)
            {
                string extend = null;
                var fileType = fileData.ContentType;
                switch (fileType)
                {
                    case "image/gif":
                        extend += ".gif";
                        break;
                    case "image/jpeg":
                        extend += ".jpg";
                        break;
                    case "image/png":
                        extend += ".png";
                        break;
                    default:
                        return ChangeAvatarError("Invalid image type (jpg, png, gif)");
                }
                var randomString = Guid.NewGuid().ToString();
                var imageName = randomString + extend;
                var thumbName = randomString + "_thumb.jpg";
                var filePath = Path.Combine(HttpContext.Server.MapPath(AppConst.DEFAULT_AVATAR_UPLOAD_DIR),
                                                   Path.GetFileName(imageName));
                var thumPath = Path.Combine(HttpContext.Server.MapPath(AppConst.DEFAULT_AVATAR_UPLOAD_DIR),
                                                   Path.GetFileName(thumbName));
                var image = Image.FromStream(fileData.InputStream, true, true);
                if (!CreateThumbImage(image, thumPath)) return ChangeAvatarError("Cannot process the image");
                fileData.SaveAs(filePath);
                avatar = AppConst.DEFAULT_AVATAR_UPLOAD_PATH + "/" + thumbName;
            }
            var userId = WebSecurity.CurrentUserId;
            diaryDB.ChangeAvatar(userId, avatar, User.Identity.Name);
            var model = new
            {
                success = true,
                avatar = avatar,
            };
            return Json(model);
        }

        private bool CreateThumbImage(Image image, string path)
        {
            Bitmap bitmap = null;
            var success = true;
            try
            {
                bitmap = new Bitmap(AppConst.AVATAR_THUMB_WIDTH, AppConst.AVATAR_THUMB_HEIGHT);
                var size = Math.Min(image.Width, image.Height);
                var clipRectangle = new RectangleF((image.Width - size) / 2, (image.Height - size) / 2, size, size);
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.Clear(Color.White);
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    g.CompositingQuality = CompositingQuality.HighQuality;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.DrawImage(image,
                        new Rectangle(0, 0, AppConst.AVATAR_THUMB_WIDTH, AppConst.AVATAR_THUMB_HEIGHT),
                        clipRectangle, GraphicsUnit.Pixel);
                } //done with drawing on "g"
                var jpgInfo =
                    ImageCodecInfo.GetImageEncoders().First(codecInfo => codecInfo.MimeType == "image/jpeg");
                using (var outputStream = new StreamWriter(path).BaseStream)
                {
                    using (var encParams = new EncoderParameters(1))
                    {
                        encParams.Param[0] = new EncoderParameter(Encoder.Quality, AppConst.THUMB_QUALITY);
                        //quality should be in the range [0..100]
                        bitmap.Save(outputStream, jpgInfo, encParams);
                    }
                }
            }
            catch
            {
                success = false;
            }
            finally
            {
                if (bitmap != null) bitmap.Dispose();
            }
            return success;
        }

        private JsonResult ChangeAvatarError(string message)
        {
            return Json(new
            {
                success = false,
                error = message,
            });
        }

        protected override void Dispose(bool disposing)
        {
            diaryDB.Dispose();
            base.Dispose(disposing);
        }
    }
}
